import logging
import os
import platform
import signal
import subprocess
import sys
import time
from typing import List

import requests

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


class ServiceManager:
    def __init__(self):
        self.venv_path = "venv"
        self.ollama_url = "http://localhost:11434"
        self.server_url = "http://localhost:8000"
        self.processes: List[subprocess.Popen] = []

    def setup_virtual_env(self) -> bool:
        """设置虚拟环境"""
        try:
            if not os.path.exists(self.venv_path):
                logger.info("创建虚拟环境...")
                subprocess.run([sys.executable, "-m", "venv", self.venv_path], check=True)

            # 获取虚拟环境中的 Python 解释器路径
            if platform.system() == "Windows":
                python_path = os.path.join(self.venv_path, "Scripts", "python.exe")
            else:
                python_path = os.path.join(self.venv_path, "bin", "python")

            # 安装依赖
            logger.info("安装依赖...")
            subprocess.run([python_path, "-m", "pip", "install", "--upgrade", "pip"], check=True)

            # 安装核心依赖
            dependencies = [
                "fastapi==0.95.2",
                "uvicorn==0.22.0",
                "requests==2.31.0",
                "pydantic==1.10.7"
            ]
            subprocess.run([python_path, "-m", "pip", "install"] + dependencies, check=True)

            # 安装其他依赖
            if os.path.exists("requirements.txt"):
                subprocess.run([python_path, "-m", "pip", "install", "-r", "requirements.txt"], check=True)

            # 验证依赖安装
            subprocess.run([python_path, "-c", "import fastapi; import uvicorn; import requests; import pydantic"],
                           check=True)
            logger.info("✓ 虚拟环境设置完成")
            return True

        except subprocess.CalledProcessError as e:
            logger.error(f"设置虚拟环境失败: {str(e)}")
            return False
        except Exception as e:
            logger.error(f"设置虚拟环境时发生错误: {str(e)}")
            return False

    def start_ollama(self) -> bool:
        """启动 Ollama 服务"""
        try:
            # 检查 Ollama 是否已运行
            response = requests.get(f"{self.ollama_url}/api/tags")
            if response.status_code == 200:
                logger.info("✓ Ollama 服务已在运行")
                return True

            # 启动 Ollama
            logger.info("启动 Ollama 服务...")
            if platform.system() == "Windows":
                process = subprocess.Popen(["ollama", "serve"],
                                           creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
            else:
                process = subprocess.Popen(["ollama", "serve"],
                                           preexec_fn=os.setsid)

            self.processes.append(process)

            # 等待服务启动
            for _ in range(10):
                try:
                    response = requests.get(f"{self.ollama_url}/api/tags")
                    if response.status_code == 200:
                        logger.info("✓ Ollama 服务启动成功")
                        return True
                except requests.exceptions.ConnectionError:
                    time.sleep(1)
                    continue

            logger.error("✗ Ollama 服务启动超时")
            return False

        except Exception as e:
            logger.error(f"启动 Ollama 服务失败: {str(e)}")
            return False

    def start_agent_server(self) -> bool:
        """启动智能代理服务"""
        try:
            # 检查服务是否已运行
            try:
                response = requests.get(f"{self.server_url}/v1/model/status")
                if response.status_code == 200:
                    logger.info("✓ 智能代理服务已在运行")
                    return True
            except requests.exceptions.ConnectionError:
                pass

            # 启动服务
            logger.info("启动智能代理服务...")
            python_path = os.path.join(self.venv_path, "Scripts",
                                       "python.exe") if platform.system() == "Windows" else os.path.join(self.venv_path,
                                                                                                         "bin",
                                                                                                         "python")

            if platform.system() == "Windows":
                process = subprocess.Popen([python_path, "run_agent.py"],
                                           creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
            else:
                process = subprocess.Popen([python_path, "run_agent.py"],
                                           preexec_fn=os.setsid)

            self.processes.append(process)

            # 等待服务启动
            for _ in range(15):
                try:
                    response = requests.get(f"{self.server_url}/v1/model/status")
                    if response.status_code == 200:
                        logger.info("✓ 智能代理服务启动成功")
                        return True
                except requests.exceptions.ConnectionError:
                    time.sleep(1)
                    continue

            logger.error("✗ 智能代理服务启动超时")
            return False

        except Exception as e:
            logger.error(f"启动智能代理服务失败: {str(e)}")
            return False

    def cleanup(self):
        """清理所有进程"""
        logger.info("正在清理服务...")
        for process in self.processes:
            try:
                if platform.system() == "Windows":
                    process.terminate()
                else:
                    os.killpg(os.getpgid(process.pid), signal.SIGTERM)
                process.wait(timeout=5)
            except Exception as e:
                logger.error(f"清理进程失败: {str(e)}")
                if platform.system() == "Windows":
                    subprocess.run(['taskkill', '/F', '/T', '/PID', str(process.pid)])
                else:
                    os.killpg(os.getpgid(process.pid), signal.SIGKILL)

        self.processes.clear()
        logger.info("服务已停止")

    def run_tests(self) -> bool:
        """运行测试流程"""
        try:
            # 1. 设置虚拟环境
            logger.info("\n1. 设置虚拟环境")
            if not self.setup_virtual_env():
                return False

            # 2. 启动 Ollama 服务
            logger.info("\n2. 启动 Ollama 服务")
            if not self.start_ollama():
                return False

            # 3. 启动智能代理服务
            logger.info("\n3. 启动智能代理服务")
            if not self.start_agent_server():
                return False

            # 4. 运行测试
            logger.info("\n4. 运行测试")
            python_path = os.path.join(self.venv_path, "Scripts",
                                       "python.exe") if platform.system() == "Windows" else os.path.join(self.venv_path,
                                                                                                         "bin",
                                                                                                         "python")
            result = subprocess.run([python_path, "test_flow.py"])

            return result.returncode == 0

        except KeyboardInterrupt:
            logger.info("\n接收到中断信号")
            return False
        except Exception as e:
            logger.error(f"\n测试过程出错: {str(e)}")
            return False
        finally:
            self.cleanup()


if __name__ == "__main__":
    manager = ServiceManager()
    success = manager.run_tests()

    if success:
        logger.info("\n✓ 所有测试通过！系统运行正常。")
        sys.exit(0)
    else:
        logger.error("\n✗ 测试失败，请检查日志")
        sys.exit(1)
